﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LogicalComponent.util;

namespace LogicalComponent.rules.grid
{
    /// <summary>
    /// The interface for a grid.  This deals with the read only interface that doesn't
    /// much care what type the tile has, only that it implements the TileInterface.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IGrid 
    {
        /// <summary>
        /// All the tiles in this grid in a flat list.
        /// </summary>
        List<ITile> AllTiles { get; }

        /// <summary>
        /// Get a tile at a given x, z coordinate.
        /// </summary>
        /// <param name="x">The x coordinate of the tile</param>
        /// <param name="z">The z coordinate of the tile</param>
        /// <returns>
        /// The tile in the given coordiante
        /// </returns>
        ITile GetTile(int x, int z);

        /// <summary>
        /// Gets the tile at the given coordinate.
        /// </summary>
        /// <param name="coordinate">The coordinate</param>
        /// <returns>
        /// The tile in the given coordinate
        /// </returns>
        ITile GetTile(Coordinate coordinate);

        /// <summary>
        /// Determines whether the given Coordinate is on this grid.
        /// </summary>
        /// <param name="coordinate">The coordiante.</param>
        /// <returns>
        ///   <c>true</c> if the given coordinate is on this grid; otherwise, <c>false</c>.
        /// </returns>
        bool IsOnGrid(Coordinate coordinate);

        /// <summary>
        /// Determines whether the given x, z is on the grid
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="z">The z.</param>
        /// <returns>
        ///   <c>true</c> if (x, z) is on the grid; otherwise, <c>false</c>.
        /// </returns>
        bool IsOnGrid(int x, int z);
    }


    /// <summary>
    /// The interface for a grid.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IGrid<T> : IGrid where T : ITile
    {
        /// <summary>
        /// All the tiles in this grid in a flat list.
        /// </summary>
        new List<T> AllTiles { get; }

        /// <summary>
        /// Get a tile at a given x, z coordinate.
        /// </summary>
        /// <param name="x">The x coordinate of the tile</param>
        /// <param name="z">The z coordinate of the tile</param>
        /// <returns>
        /// The tile in the given coordiante
        /// </returns>
        new T GetTile(int x, int z);

        /// <summary>
        /// Gets the tile at the given coordinate.
        /// </summary>
        /// <param name="coordinate">The coordinate</param>
        /// <returns>
        /// The tile in the given coordinate
        /// </returns>
        new T GetTile(Coordinate coordinate);

        /// <summary>
        /// Sets a tile at the given coordinate.
        /// </summary>
        /// <param name="x">The x coordinate of the tile to set.</param>
        /// <param name="z">The z coordinate of the tile to set</param>
        /// <param name="tile">The tile.</param>
        void SetTile(int x, int z, T tile);

        /// <summary>
        /// Sets a tile at the given coordinate.
        /// </summary>
        /// <param name="coordinate">The coordinate.</param>
        /// <param name="tile">The tile.</param>
        void SetTile(Coordinate coordinate, T tile);

        /// <summary>
        /// Creates the tile.
        /// </summary>
        /// <param name="c">The c.</param>
        void CreateTile(Coordinate c);

        /// <summary>
        /// Creates the tile.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="z">The z.</param>
        void CreateTile(int x, int z);

        /// <summary>
        /// Destriys the tile.
        /// </summary>
        /// <param name="c">The c.</param>
        void DestroyTile(Coordinate c);

        /// <summary>
        /// Destroys the tile.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="z">The z.</param>
        void DestroyTile(int x, int z);
    }
}
